<template>
	<div class="newVideo">
		<h2>
			<el-page-header @back="$utils.goBack()" :content="$route.query._ ? '更新课程所属视频' : '发布课程所属视频' ">
			</el-page-header>
		</h2>
		<el-divider></el-divider>
		<el-container>
			<el-main>
				<el-form ref="dynamicValidateForm" label-width="100px" class="demo-dynamic">
					
					<div v-for="(item, index) in dynamicValidateForm" :key="index">
						<el-row>
							<el-col :span="24">
								<div class="grid-content bg-purple-dark">
									<h3>第{{ index + 1 }}讲</h3>
									<el-button style="float: right" @click="addDomain">增加视频章节</el-button>
									<el-button
										style="float: right;margin-right: 10px;"
										icon="el-icon-delete"
										@click.prevent="removeDomain(index,item)">
									 删除
									</el-button>
									<el-divider></el-divider>
								</div>
							</el-col>
						</el-row>
						<el-form-item
							label="视频标题">
							<el-input clearable v-model="item.courseTitle"></el-input>
						</el-form-item>
						
						<el-form-item label="视频介绍">
							<el-input autosize type="textarea" v-model="item.courseDesc"></el-input>
						</el-form-item>
						
						<el-form-item label="免费试看？">
							<el-switch
								v-model="item.courseAudition"
								active-color="#13ce66"
								inactive-color="#ff4949"
								active-text="能"
								inactive-text="不能">
							</el-switch>
							<br>
							<el-link type="danger" :underline="false">提示: 如果课程设置为收费，那么可以选择性开启视频章节的试听功能。
								<br>被开启试听的视频章节可免费观看，反之则需用户购买。如果是免费课程，该设置不会生效。</el-link>
						</el-form-item>
						
						<el-form-item label="课程视频">
							<el-upload
								class="avatar-uploader"
								drag
								action="http://upload.qiniu.com/"
								:before-upload="beforeUpload"
								:show-file-list="true"
								:data="UploadFileData"
								:on-success="handleSuccess">
									<img v-if="item.courseVideoImg != null" :src="item.courseVideoImg" class="avatar">
									<i v-else class="el-icon-video-camera-solid" @click="getIndexKey(index)"></i>
									<div class="el-upload__text" @click="getIndexKey(index)">拖拽或点击上传视频</div>
									<div class="el-upload__tip" slot="tip">单次视频上传不超过500MB</div>
							</el-upload>
						</el-form-item>
						
					</div>
			
					
					<el-form-item>
						<el-button v-if="this.$route.query._"
						           type="primary"
						           :loading="ShowLoading"
						           @click="submitUpdateVideo('dynamicValidateForm')">
							发布更新
						</el-button>
						
						<el-button v-else
						           type="primary"
						           :loading="ShowLoading"
						           @click="submitForm('dynamicValidateForm')">
							发布视频
						</el-button>
						
					</el-form-item>
				</el-form>
			</el-main>
		</el-container>
	</div>
</template>

<script lang="ts">
	import { Vue, Component, Watch } from "vue-property-decorator"
	import axios from "axios"
	
	@Component
	export default class newVideoComponents extends Vue {
		
		// 是否展示加载进度
		private ShowLoading:boolean = false;
		
		// 页面的核心数据
		public dynamicValidateForm:Array = [
			{
				courseObjectid: null,
				courseTitle: null,
				courseDesc: null,
				courseAudition: false,
				courseVideoUrl: null,
				courseVideoImg: null
			}
		];
		
		// 记录被修改数据的下标
		private NewTargetArrayIndex = [];
		
		// 用户上传视频的所在的数组的对象下标
		public indexKey:number = null;
		
		// 上传视频需要发送给 七牛 的数据
		public UploadFileData:Object = {
			token: null, // token
			key: null    // key 上传到七牛的视频文件名
		};
		
		public VideoHlsToken: Object;
		
		
		created () {
			if(this.$route.query._) {
				this.getVideoList();
			}
		}
		
		/**
		 * 获取课程所属的视频章节信息
		 */
		public async getVideoList (): void {
			let VideoList = await this.$http.post({
				url: '/admin/getVideoList',
				params: { id: this.$route.params.id }
			});
			if(VideoList.status == 200) {
				this.dynamicValidateForm = VideoList.result;
				this.Watch();
			}
			
		}
		
		/**
		 * 网络请求完成后，对请求到的数组遍历后得到Object，然后进行底层的set观察拦截
		 * 当Object数据被修改，返回被修改的Object所在的数组中下标，然后存储下标，
		 * 在提交数据的时候，通过记录被修改数据的下标数组去 所有 数据的数组中匹配拿出管理员
		 * 只修改过的部分数据，未修改的不拿，然后提交后端。
		 */
		public async Watch (): void {
			// 观测数据
			this.$utils.WatchData(this.dynamicValidateForm, (index) => {
				// 第一次运行，直接 push 存储下标
				if(this.NewTargetArrayIndex.length == 0) {
					this.NewTargetArrayIndex.push(index)
				} else {
					// 避免修改单一对象的其他属性时，下标被重复存储
					this.NewTargetArrayIndex.indexOf(index) <= -1
						? this.NewTargetArrayIndex.push(index)
						: ''
				}
				console.log(this.NewTargetArrayIndex);
				// 自己的观察 和 vue 底层观察冲突，需要强制页面刷新
				this.$forceUpdate();
				
			});
		}
		
		/**
		 * 第一次直接提交课程所属视频的数据（创建数据）
		 */
		public async submitForm(formName:string): void {
			this.ShowLoading = true;
			console.log("课程数据：",JSON.stringify(this.dynamicValidateForm));
			let data = await this.$http.post({
				url: '/admin/updateCourseVideo',
				params: this.dynamicValidateForm
			});
			if(data.result.res == "success") {
				this.$notify({
					title: '提示',
					message: '视频全部上传成功',
					type: 'success'
				});
			}else {
				this.$notify({
					title: '提示',
					message: '视频上传失败',
					type: 'success'
				});
			}
			this.ShowLoading = false;
		}
		
		/**
		 * 第二次更新课程下面已经存在的所属视频信息（更新数据）
		 * 通过对象内部是否包含objectID判断对象，包含表示update操作
		 * 不包含表示insert操作
		 */
		public async submitUpdateVideo(): void {
			this.ShowLoading = true;
			let NewArray:Array<Object> = [];
			this.NewTargetArrayIndex.forEach(value => {
				NewArray.push(this.dynamicValidateForm[value])
			});
			
			let again = await this.$http.post({
				url: '/admin/againUpdateCourseVideo',
				params: NewArray
			});
			this.$notify({
				title: '提示',
				message: '课程信息发布成功',
				type: 'success'
			});
			this.ShowLoading = false;
		}
		
		/**
		 * 保存被点击的对象下标
		 * @param key
		 */
		public getIndexKey(key: number): void {
			this.indexKey = key;
		}
		
		/**
		 * 视频上传前请求服务器获取七牛需要的 token
		 * @param file
		 */
		public async beforeUpload(file: File): void {
	
			let token = await this.$http.post({
				url: '/admin/token',
				params: {
					filename : file.name
				}
			});
			// 存储hls的token对象
			this.VideoHlsToken = token.result.hls;
			this.UploadFileData.token = token.result.token;
			this.UploadFileData.key = file.name;
		}
		
		/**
		 * 主视频上传到七牛云后，发送 post multipart/form-data 的请求并传递token
		 * 通知七牛对 xx空间内的 xx视频进行hls切片存储到 xx空间中，任务都在token中被加密
		 */
		async handleSuccess(response, file, fileList): void {
			/**
			 * 手动构造POST表单数据，
			 * token: nodejs后端生成的token，视频上传前已从服务器获取保存了
			 * key: 用户选中的视频文件名，必须和后端返回的token中被加密的文件名一致，基本上不用管
			 * file：七牛需要的用户选中文件的File对象，也就是 input(type="file") 选中的File 对象(BufferSource)
			 * 需要解决的问题：七牛视频切片是耗时的任务，所以ajax会超时从而被axios响应拦截器拦截到无响应的错误，页面有错误弹窗
			 * 方法：单独封装 axios 的响应拦截器，然后在 axios 工具类导入使用，在newvideo页面 通知七牛视频切片的时候可以移除响应
			 *      拦截器。
			 */
			let formData:FormData = new FormData();
			formData.append("token", this.VideoHlsToken.token)
			formData.append("key", response.key)
			formData.append("file", file.raw)
			
			// 向七牛发送HLS切片通知
			await this.$http.post({ 
				url: 'http://upload.qiniu.com/', params: formData, headers: { 'Content-Type': 'multipart/form-data' }
			});
			
			// 视频缩略图地址
			this.dynamicValidateForm[this.indexKey].courseVideoImg = `http://static.geekhelp.cn/${response.key}?vframe/png/offset/0`
			// 视频地址
			this.dynamicValidateForm[this.indexKey].courseVideoUrl = this.VideoHlsToken.filePath
			// 视频所属课程的 课程ID
			this.dynamicValidateForm[this.indexKey].courseObjectid = this.$route.params.id;
			// 手动刷新页面，否则新增出来的章节视频预览图地址不显示
			this.$forceUpdate();
			
		}
		
		/**
		 * 删除视频节点
		 * @param item
		 */
		public async removeDomain(index:number ,item:Object): void {
			if(this.dynamicValidateForm.length == 1) {
				this.$notify({
					title: '提示',
					message: '必须保留至少一个章节！',
					type: 'error'
				});
			} else {
				let index = this.dynamicValidateForm.indexOf(item);
				if (index !== -1) {
					this.$confirm(`此操作将删除 [ 第${index+1}讲 ] 视频, 请三思！`, '提示', {
						confirmButtonText: '确定',
						cancelButtonText: '取消',
						type: 'warning'
					}).then(() => {
						this.dynamicValidateForm.splice(index, 1);
						this.$notify({
							title: '提示',
							message: '视频章节删除成功',
							type: 'success'
						});
						this.NewTargetArrayIndex.splice(index,1);
						this.Watch();
					}).catch(() => {
					
					})
				}
				
			}
			
		}
		
		/**
		 * 添加更多视频章节的事件
		 */
		addDomain(): void {
			this.dynamicValidateForm.push({
				courseTitle: null,
				courseDesc: null,
				courseAudition: false,
				courseVideoUrl: null
			});
			this.$notify({
				title: '提示',
				message: '视频章节添加成功',
				type: 'success'
			});
	
			if(this.$route.query._ == undefined) {
				console.log("不需要监听数据");
			}else {
				console.log("需要Watch监听数据");
				this.Watch()
			}
		}
		
		
	}
</script>

<style scoped lang="less">
 h3 {
	 display: inline-block;
 }
 .el-upload-dragger .el-icon-video-camera-solid {
	 font-size: 67px;
	 color: #C0C4CC;
	 margin: 40px 0 16px;
	 line-height: 50px;
 }
 .avatar {
	 width: 100%;
 }
</style>